﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace TestCSharp
{
    public class HJVerifyEngine
    {
        public const int TEMPLATESIZE = 2560;

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_FaceEngineIntial", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_FaceEngineIntial(int nMinIOD, int nRollAngle);


        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_VerifyTwoImage", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_VerifyTwoImage(IntPtr pImage1, IntPtr pImage2, out float fScore, out int bSuccess);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_ExtractFeatureByFace", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_ExtractFeatureByFace(int nChannelIndex, IntPtr pImage, HJFaceModel model, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] feature);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CompareTwoFeature", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_CompareTwoFeature(byte[] feature1, byte[] feature2, out float fScore);
        //人脸检测
        //nChannelIndex[in]:线程索引号，暂时先开通 0 1 2 三个索引
        //pImage[in]：图片
        //models[in]：检测结果，外部分配大小，大小为nMaxFace，即预期要检测的最多人脸数
        //nMaxFace[in]：预期要检测的最多人脸数
        //nFaceNum[out]：实际检测到的人脸数
        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_DetectFacesEx", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_DetectFacesEx(int nChannelIndex, IntPtr pImage, [Out, MarshalAs(UnmanagedType.LPArray)]HJFaceModel[] models, int nMaxFace, out int nFaceNum);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_LivenessDetectFaces", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_LivenessDetectFaces(int nChannelIndex, IntPtr pImage, [Out, MarshalAs(UnmanagedType.LPArray)] HJFacialDetails[] models, int nMaxFace, out int nFaceNum);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_FaceEngineFree", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_FaceEngineFree();


        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_LoadImageFromFile", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_LoadImageFromFile(string szFileName, out IntPtr pImage);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_LoadImageFromBitmap24", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_LoadImageFromBitmap24([In, MarshalAs(UnmanagedType.LPArray)]byte[] pBmp24Buf, int iWidth, int iHeight, out IntPtr pImage);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_FreeImage", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern int HJ_FreeImage(IntPtr image);


        ///////////////////////////////////////摄像头相关函数//////////////////////////////////////////////////////
        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraManagerGetCount", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraManagerGetCount(out int pCameraCount);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraManagerGetCamera", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr HJ_CameraManagerGetCamera(int iCameraIndex);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraGetResolution", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraGetResolution(IntPtr pCamera, out int pWidth, out int pHeight);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraGetCurrentFrame", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraGetCurrentFrame(IntPtr pCamera, out IntPtr pFrame, out int pFrameSize);

        //nFlip[in]:旋转角度 0 - 不旋转 1 - 旋转90度  2 - 旋转180度  3 - 旋转270度  4 - 垂直镜像  5 - 水平镜像
        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraGetCurrentFrameFlip", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraGetCurrentFrameFlip(IntPtr pCamera, out IntPtr pFrame, out int pFrameSize, int nFlip);

        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraGetName", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraGetName(IntPtr pCamera, byte[] sName, int nBufferSize);
       
        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraStartCapturing", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraStartCapturing(IntPtr pCamera);
       
        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraStartCapturingWithSize", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraStartCapturingWithSize(IntPtr pCamera, int nWidth, int nHeight);//指定视频大小
        
        [DllImport("HJVerifyEngine.dll", EntryPoint = "HJ_CameraStopCapturing", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool HJ_CameraStopCapturing(IntPtr pCamera);


        /// <summary>
        /// 将二进制字节数组转换为图像
        /// </summary>
        /// <param name="byteArray">二进制字节数组</param>
        /// <returns>图像</returns>
        public static IntPtr ByteArrayToBitmapByteArray(byte[] byteArray)
        {
            IntPtr pImage = new IntPtr();
            try
            {
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream(byteArray))
                {
                    using (Bitmap image = new Bitmap(ms))
                    {
                        using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
                        {
                            image.Save(ms1, System.Drawing.Imaging.ImageFormat.Bmp);
                            byte[] p = ms1.ToArray();
                            HJVerifyEngine.HJ_LoadImageFromBitmap24(p, image.Width, image.Height, out pImage);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ByteArrayToBitmap：{0}", ex.Message);
            }
            return pImage;
        }

        public static IntPtr BitmapToHJImage(Bitmap bmp)
        {
            IntPtr pImage = new IntPtr();
            try
            {
                BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                using (Bitmap tmp = new Bitmap(bmp.Width, bmp.Height, bd.Stride, PixelFormat.Format24bppRgb, bd.Scan0))
                {
                    using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
                    {
                        tmp.Save(ms1, System.Drawing.Imaging.ImageFormat.Bmp);
                        byte[] p = ms1.ToArray();
                        HJVerifyEngine.HJ_LoadImageFromBitmap24(p, bmp.Width, bmp.Height, out pImage);
                    }
                }
                bmp.UnlockBits(bd);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ByteArrayToBitmap：{0}", ex.Message);
            }
            return pImage;
        }

        #region GetPicThumbnail
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="sFile">原图片</param>
        /// <param name="dFile">压缩后保存位置</param>
        /// <param name="dHeight">高度</param>
        /// <param name="dWidth">宽度</param>
        /// <param name="flag">压缩质量 1-100</param>
        /// <returns></returns>

        public static bool GetPicThumbnail(string sFile, string dFile, int dHeight, int dWidth, int flag)
        {
            System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            int sW = 0, sH = 0;
            //按比例缩放
            Size tem_size = new Size(iSource.Width, iSource.Height);
            if (tem_size.Width > dHeight || tem_size.Width > dWidth) //将**改成c#中的或者操作符号
            {
                if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);
            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
            g.Dispose();
            //以下代码为保存图片时，设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();

                ImageCodecInfo jpegICIinfo = null;

                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();

            }
        }
        #endregion

        public static IntPtr BitmapToHJImage2(Bitmap bmp)
        {
            IntPtr pImage = new IntPtr();
            try
            {
                using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
                {
                    bmp.Save(ms1, System.Drawing.Imaging.ImageFormat.Bmp);
                    byte[] p = ms1.ToArray();
                    HJVerifyEngine.HJ_LoadImageFromBitmap24(p, bmp.Width, bmp.Height, out pImage);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ByteArrayToBitmap：{0}", ex.Message);
            }
            return pImage;
        }
    }

    public struct HJPoint
    {
        public int x;
        public int y;
    }

    public struct HJRect
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }


    public struct HJSize
    {
        public int cx;
        public int cy;
    }

    public struct HJFaceModel
    {
        public HJRect rcFace;//人脸矩形框
        public HJPoint ptLeftEye;//左眼坐标
        public HJPoint ptRightEye;//右眼坐标
        public float fConfidence; //人脸检测置信度
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] pContext;
    }
    /// <summary>
    /// 人脸检测，活体检测
    /// </summary>
    public struct HJFacialDetails
    {
        public HJRect rcFace;//人脸矩形框
        public HJPoint ptLeftEye;//左眼坐标
        public HJPoint ptRightEye;//右眼坐标
        public float fConfidence; //人脸检测置信度
        public int yaw;//-90 to +90，左转负数，右转正数
        public int pitch;//-90 to +90, 抬头负数，低头正数
        public int roll;// -90 to +90,左倾斜负数，右倾斜正数
        public int nEyeStatus;//人眼状态   1 --- 睁眼  0 --- 闭眼
        public int nMouthStatus;//嘴巴状态 1 --- 张嘴  0 --- 闭嘴
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] pContext;
    }
}